#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <queue>
#include <pthread.h>
#define SIZE 5
using namespace std;
template <class T>
class BlockQueue
{
public:
        BlockQueue(int capacity=SIZE)
        :_capacity(capacity)
        {
            pthread_mutex_init(&_mutex,NULL);
            pthread_cond_init(&_cum,NULL);
            pthread_cond_init(&_pro,NULL);
        }
        ~BlockQueue()
        {
            pthread_mutex_destroy(&_mutex);
            pthread_cond_destroy(&_cum);            pthread_cond_destroy(&_pro);
            _capacity=0;
        }

        bool IsFull()
        {
            return _capacity==_q.size();
        }
        bool IsEmpty()
        {
            return 0==_q.size();
        }
        void push(const T& data)
        {
            pthread_mutex_lock(&_mutex);
            while(IsFull())
            {
                pthread_cond_wait(&_pro,&_mutex);
            }
            _q.push(data);
            pthread_mutex_unlock(&_mutex);
            pthread_cond_signal(&_cum);
        }

        void pop(T& out)
        {
            pthread_mutex_lock(&_mutex);
            while(IsEmpty())
            {
                pthread_cond_wait(&_cum,&_mutex);
            }
            out=_q.front();
            _q.pop();
            pthread_mutex_unlock(&_mutex);
            pthread_cond_signal(&_pro);
        }


private:
    queue<T> _q;
    pthread_mutex_t _mutex;
    pthread_cond_t _cum;
    pthread_cond_t _pro;
    int _capacity;
};
